perf(attn): cp.async double-buffered KV staging in GQA flash-decode split#187
Closed
real-venus wants to merge 1 commit into
Closed
perf(attn): cp.async double-buffered KV staging in GQA flash-decode split#187real-venus wants to merge 1 commit into
real-venus wants to merge 1 commit into
Conversation
…plit The long-context GQA split (fa_split_gqa_kernel) stages each KV tile into shared memory with a synchronous uint4 __ldg, then a __syncthreads barrier, then reduces it. The warps stall at that barrier waiting on the global KV read — the dominant cost in 16k/4k decode. Add fa_split_gqa_pipe_kernel: a double-buffered variant that prefetches tile N+1 with cp.async into a second smem buffer while tile N is being reduced, so the KV load latency overlaps the QK/softmax/V compute instead of stalling. cp.async issues 16-byte (uint4 = 8xbf16) .cg copies — same granularity as the existing vectorized staging — via inline PTX (header-free, safe under NVRTC device-only). A 2-stage commit/wait_group pipeline keeps exactly one tile in flight; barriers are placed so the buffer being refilled is WAR-safe against the prior tile's reads. The math is unchanged and the emitted partials are byte-identical to fa_split_gqa_kernel (same KV values reach smem, only earlier), so the top-1 / KL accuracy gate is unaffected by construction. Selected by default for the GQA long-context path; SPARKINFER_FAPIPE=0 restores the single-buffer kernel for A/B benchmarking. Two K/V buffers double the per-tile smem to 4*TILE*128*2B (~14 KB), well within the default 48 KB.
Member
|
Closed due to inactivity — not updated in over 2 days. Feel free to reopen with updates. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
perf(attn): overlap the long-context KV load with compute in the GQA flash-decode split viacp.asyncdouble-buffering. The existing GQA split (fa_split_gqa_kernel) stages each KV tile into shared memory with a synchronousuint4 __ldg, hits a__syncthreadsbarrier, then reduces it — so the warps stall on the global KV read that dominates 4k/16k decode. This addsfa_split_gqa_pipe_kernel, which prefetches tile N+1 withcp.asyncinto a second smem buffer while tile N is being reduced, hiding the KV-load latency behind the QK/softmax/V math.What changed
kernels/csrc/cuda/attention/flash_decode_split.cu(only file touched).fa_split_gqa_pipe_kernel<HEAD_DIM, GQA, TILE>— a 2-stagecp.asyncpipeline over the KV tiles. 16-byte (uint4= 8×bf16).cgcopies (same granularity as the current vectorized staging), issued via inline PTX so it stays header-free and NVRTC-device-only safe. Acommit_group/wait_grouppair keeps exactly one tile in flight; barriers are placed so the buffer being refilled is WAR-safe against the prior tile's reads.SPARKINFER_FAPIPE=0restores the single-bufferfa_split_gqa_kernelfor A/B.4·TILE·128·2B(~14 KB) — well within the 48 KB default, no opt-in needed.Correctness
The math is unchanged and the emitted partials are byte-identical to
fa_split_gqa_kernel— the same KV values reach shared memory, only prefetched a tile earlier. So the top-1 / KL accuracy gate is unaffected by construction.accuracy.sh(RTX 5090, Qwen3-30B-A3B Q4_K_M): top-1 =<0.xx>, KL =<0.0xx>(pass).Proof of speedup
sm_120)Env: RTX 5090 ·
sm_120· CUDA<12.8/13>· Qwen3-30B-A3B Q4_K_M · 128 generated tokens.Decode tok/s (end-to-end, from
bench/scripts/bench.sh):